package com.liveinstars.im.endpoint;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.liveinstars.im.core.Session;
import com.liveinstars.im.core.SessionManager;
import com.liveinstars.api.im.ImDirectMemoryApi;
import com.onepiece.cache.service.CacheService;
import com.onepiece.shipelves.common.Result;
import com.onepiece.shipelves.common.utils.CacheUtil;
import io.netty.util.internal.PlatformDependent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author: zhouze
 * @date: 2020/2/28
 */
@RestController
public class ImDirectMemoryEndPoint implements ImDirectMemoryApi {

    private static final Logger logger = LoggerFactory.getLogger(ImDirectMemoryEndPoint.class);

    private static final int _1K = 1024;
    private static final String KEY = "netty_direct_memory";
    private static final String DIRECT_LIMIT_MEMORY = "netty_direct_limit_memory";

    @Autowired
    private SnowFlake snowFlake;

    @Autowired
    CacheService cache;

    @Override
    public Result<String> getDirectMemory() {
        Result<String> result = new Result<>();
        String s = doReport();
        result.setData(s);
        return result;
    }

    @Override
    public Result<List<String>> getImUserTokenChatserverList(@RequestParam("user_id") Long userId) {
        Result<List<String>> result = new Result<>();
        String key = CacheUtil.getImUserTokenChatserverList(userId);
        Set<String> smembers = cache.smembers(key);
        List<String> list = Lists.newArrayList(smembers);
        result.setData(list);
        return result;
    }

    @Override
    public Result<Map<String, String>> getSessionMap(){
        Result<Map<String, String>> result = new Result<>();
        Map<String, Session> sessionMap = SessionManager.getSessionMap();
        Map<String, String> serverChannelIdMap = SessionManager.getServerChannelIdMap();
        Map<String, String> map = Maps.newHashMap();
        for (String key : sessionMap.keySet()) {
            map.put(key, String.valueOf(sessionMap.get(key).hashCode()));
        }
        for (String key : serverChannelIdMap.keySet()) {
            map.put(key, serverChannelIdMap.get(key));
        }
        result.setData(map);
        return result;
    }

    @Override
    public Result<HashMap<String, Long>> getClockTimestamp() {
        Result<HashMap<String, Long>> result = new Result<>();
        long myClock = SystemClock.now();
        long systemClock = System.currentTimeMillis();
        long id = snowFlake.nextId();
        HashMap<String, Long> map = new HashMap<>();
        map.put("myClock", myClock);
        map.put("systemClock", systemClock);
        map.put("id", id);
        result.setData(map);
        return result;
    }

    private String doReport() {
        try {
            Field field = ReflectionUtils.findField(PlatformDependent.class, "DIRECT_MEMORY_COUNTER");
            field.setAccessible(true);
            AtomicLong directMemory = (AtomicLong)field.get(PlatformDependent.class);
            int memory1nKb = (int) (directMemory.get()/_1K);
            long directLimit1nKb = PlatformDependent.maxDirectMemory() / _1K;
            logger.info("{} : {}k limit: {}k", KEY, memory1nKb, directLimit1nKb);
            String msg = KEY + ": " + memory1nKb + "KB " + DIRECT_LIMIT_MEMORY + ": " + directLimit1nKb + "KB";
            return msg;
        } catch (Exception e) {

        }
        return "";
    }
}
